<template>
  <view class="order-tag-list" v-if="tags && tags.length > 0">
    <scroll-view class="order-tag-scroll" scroll-x="true" :show-scrollbar="false" enhanced="true" @scroll="handleScroll">
      <view class="order-tag-scroll-inner">
        <!-- 标签列表 -->
        <view class="order-tag-item" v-for="(item, index) in tags" :key="index">
          {{ item }}
        </view>
      </view>
    </scroll-view>
    <view class="shadow" v-if="showShadow"></view>
  </view>
  <view v-else style="height: 16rpx"></view>
</template>

<script setup>
  import { ref, watch, nextTick, getCurrentInstance } from 'vue'
  import { throttle } from 'lodash'

  const props = defineProps({
    tags: {
      type: Array,
      default: () => [],
    },
  })

  const showShadow = ref(false)

  const _this = getCurrentInstance()
  // 判断是否溢出
  const checkOverflow = (scrollLeft = 0) => {
    uni
      .createSelectorQuery()
      .in(_this.proxy)
      .select('.order-tag-scroll')
      .fields(
        { size: true, scrollOffset: true }, // 获取 width/height/scrollWidth/scrollHeight 等
        (rect) => {
          const containerWidth = rect.width
          const containerScrollWidth = rect.scrollWidth
          // 小程序中 uni.createSelectorQuery() 返回的尺寸通常是浮点数。
          // 可能会出现以下情况，没有滚动条的情况下，两个 width 不等（340.5，341）
          // 原因有以下几种：
          // 1. 浮点数精度问题
          // 2. padding / margin / flex-gap 的影响
          // 3. enhanced 模式下的 scroll-view 渲染差异
          // 因此，需要设置一个合理的容差值，来避免误判。
          const THRESHOLD = 1 // 设置一个合理的容差值
          showShadow.value =
            scrollLeft > 0
              ? containerScrollWidth >= containerWidth + scrollLeft + THRESHOLD
              : containerScrollWidth > containerWidth + THRESHOLD
        },
      )
      .exec()
  }

  watch(
    () => props.tags,
    (newVal) => {
      if (newVal && newVal.length > 0) {
        nextTick(() => {
          checkOverflow()
        })
      }
    },
    { immediate: true },
  )

  // 滚动时触发
  const throttledCheck = throttle((scrollLeft) => checkOverflow(scrollLeft), 20)
  const handleScroll = (e) => {
    const scrollLeft = e.detail?.scrollLeft || 0
    throttledCheck(scrollLeft)
  }
</script>

<style lang="less" scoped>
  .order-tag-list {
    padding: 0;
    white-space: nowrap; // 防止换行
    overflow-x: auto; // 水平滚动
    position: relative;
    height: 64rpx;
    padding-top: 16rpx;
    .order-tag-scroll {
      display: flex;
      align-items: center;
      .order-tag-scroll-inner {
        display: flex;
        .order-tag-item {
          height: 16px;
          line-height: 14px;
          font-size: 12px;
          padding: 0px 6px;
          border-radius: 9px;
          border: 1px solid #f5d6a2;
          color: #e59b1c;
        }
        .order-tag-item + .order-tag-item {
          margin-left: 20rpx;
        }
      }
    }
    .shadow {
      position: absolute;
      right: 0;
      top: 0;
      width: 40rpx;
      height: 64rpx;
      background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #ffffff 100%);
    }
  }
</style>
